import base64
import csv
import json
import time
from urllib.parse import quote

from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from django.views.decorators.csrf import csrf_exempt
from langchain_core.prompts import PromptTemplate

from tools.myjwt import mjwt
import requests
from django.shortcuts import render, redirect
from rest_framework.response import Response

from app.serial import UserSerializer, ThirdSerializer, GoodsSerializer
from app.models import User, ThirdUser, UserBrowse, Godds
from rest_framework.views import APIView
# Create your views here.
from tools.Sf_factory import f
from tools.myredis import r
from tools.bdapi import baidu, face
from django.http import HttpResponse

import os


class Dingtalk(APIView):
    def get(self, request):
        params = [
            "redirect_uri=http://localhost/sflogin",
            "response_type=code",
            "client_id=ding2t4tjfshfqrsylb9",
            "scope=openid",
            "prompt=consent"
        ]
        url = 'https://login.dingtalk.com/oauth2/auth?' + ('&'.join(params))
        return Response({'url': url})


class DingtalkCallback(APIView):
    def get(self, request):
        code = request.GET.get("code")

        if not code:
            return Response({'msg': '缺少参数'})

        data = {
            "grantType": "authorization_code",
            "clientId": "ding2t4tjfshfqrsylb9",
            "clientSecret": "3tqQQ9sA5IIwSGsRsECmn84GfA1Cba1d7NT5vCFIVDn7XhPgIsVZ6CmPO22VoyZJ",
            "code": code

        }
        resp = requests.post('https://api.dingtalk.com/v1.0/oauth2/userAccessToken', json=data).json()

        access_token = resp.get('accessToken')

        # 获取用户信息
        hearders = {'x-acs-dingtalk-access-token': access_token}
        resp = requests.get('https://api.dingtalk.com/v1.0/contact/users/me', headers=hearders).json()
        print(resp)
        name = resp.get('nick')
        uid = resp.get('openId')
        phone = resp.get('mobile')

        # 登录，写入三方登录表和用户表
        sflogin = ThirdUser.objects.filter(uid=uid, type=1).first()
        print(sflogin, 1111111111111111111111111111111111111)
        if not sflogin:
            user = User.objects.filter(phone=phone).first()
            if not user:
                userinfo = {
                    "name": name,
                    "phone": phone,

                }
                us = UserSerializer(data=userinfo)
                if us.is_valid():
                    us.save()
                else:
                    return Response({'code': 10001, "msg": us.errors})
            else:
                print(999999999999999999999999999999999)
                third_user = {
                    "type": 1,
                    "user": user.id,
                    "uid": uid,
                    "token": access_token
                }
                sf = ThirdSerializer(data=third_user)

                if sf.is_valid():
                    sf.save()
                else:
                    return Response({'code': 10001, "msg": sf.errors})

        else:

            user = sflogin.user
            print(user, 6666666666666666666666666)
            sflogin.token = access_token
            sflogin.save()
        payload = {
            "userid": user.id,
            "phone": user.phone,
            "name": user.name,
            "exp": int(time.time() + 60 * 60 * 2)
        }
        token = mjwt.jwt_encode(payload)
        payload['exp'] = int(time.time() + 60 * 60 * 4)
        # token续命
        refresh_token = mjwt.jwt_encode(payload)
        query = [
            f"userid={payload['userid']}",
            f"username={payload['name']}",
            f"token={token}",
            f"refreshToken={refresh_token}"
        ]
        return Response({'code': 200, 'token': token})


class Sfget(APIView):
    def get(self, request):
        obj = ThirdUser.objects.all()
        ser = ThirdSerializer(instance=obj, many=True)
        return Response(ser.data)


class Sflogin(APIView):
    def get(self, request):
        type = request.GET.get("type")

        obj = f.create_f(int(type)).get_url()
        return Response({'url': obj})

    def post(self, request):
        code = request.data.get("code")
        print(code,1111111111111111111111111111)
        type = request.data.get("type")
        print(type,222222222222222222222222)
        if not code:
            return Response({'msg': '缺少参数'})

        obj = f.create_f(int(type)).call_back(code)
        name = obj[0].get('nick')
        uid = obj[0].get('openId')
        phone = obj[0].get('mobile')

        # 登录，写入三方登录表和用户表
        sflogin = ThirdUser.objects.filter(uid=uid, type=1).first()
        print(sflogin, 1111111111111111111111111111111111111)
        if not sflogin:
            user = User.objects.filter(phone=phone).first()
            if not user:
                userinfo = {
                    "name": name,
                    "phone": phone,

                }
                us = UserSerializer(data=userinfo)
                if us.is_valid():
                    us.save()
                else:
                    return Response({'code': 10001, "msg": us.errors})
            else:
                print(999999999999999999999999999999999)
                third_user = {
                    "type": 1,
                    "user": user.id,
                    "uid": uid,
                    "token": obj[1]
                }
                sf = ThirdSerializer(data=third_user)

                if sf.is_valid():
                    sf.save()
                else:
                    return Response({'code': 10001, "msg": sf.errors})

        else:

            user = sflogin.user

            sflogin.token = obj[1]
            sflogin.save()
        payload = {
            "userid": user.id,
            "phone": user.phone,
            "name": user.name,
            "exp": int(time.time() + 60 * 60 * 2)
        }
        token = mjwt.jwt_encode(payload)
        payload['exp'] = int(time.time() + 60 * 60 * 4)
        # token续命
        refresh_token = mjwt.jwt_encode(payload)
        query = [
            f"userid={payload['userid']}",
            f"username={payload['name']}",
            f"token={token}",
            f"refreshToken={refresh_token}"
        ]
        return Response({'code': 200, 'token': token})


# 上传图片
from django.http import JsonResponse
from tools.ali_oss import aliyun_oss


@csrf_exempt
def upload_to_oss(request):
    """
    文件上传视图，将文件上传到阿里云 OSS
    """
    if request.method == 'POST' and request.FILES.get('file'):
        file_obj = request.FILES['file']  # 获取上传的文件
        file_name = f"idcard/{file_obj.name}"  # 生成文件名（可以自定义路径）

        file_url = aliyun_oss.upload_file(file_obj, file_name)

        if file_url:
            return JsonResponse({'status': 'success', 'file_url': file_url})
        else:
            return JsonResponse({'status': 'error', 'message': '文件上传失败'})

    return JsonResponse({'status': 'error', 'message': '无文件上传'})


class IdCardView(APIView):
    def get(self, request):

        url = request.GET.get('url')
        r.list_push('idcardlist', url)
        return Response({'code': 200, 'msg': 'ok', 'data': {'url': url}})

    def post(self, request):
        blist = r.list_lrange('idcardlist', 0, 10)
        if blist:
            for i in blist:
                picurl = i.decode('utf-8')
                print(picurl)
                mes = baidu.idcard(picurl)
                print(mes)
                # 存入redis
                r.set_str(picurl, json.dumps(mes))
                r.list_del('idcardlist', picurl)
        return Response({'code': 200, 'msg': 'ok'})


class BaiduUsermes(APIView):
    def get(self, request):
        url = request.GET.get('url')
        mes = r.get_str(url)
        code = 10010
        if mes:
            mes = json.loads(mes)
            code = 200
            r.str_del(url)
        return Response({'code': code, 'msg': mes})


class FaceRecognitionView(APIView):
    # 允许处理文件上传
    # parser_classes = (MultiPartParser, FormParser)
    def post(self, request):

        img1_url = request.data.get('img1_url')  # OSS 图片 URL
        img2_base64 = request.data.get('img2')  # 视频截图 Base64 数据

        if not img1_url or not img2_base64:
            return Response({'code': 400, 'msg': '缺少图片数据'}, status=400)

        try:
            # 下载 OSS 图片
            response = requests.get(img1_url)
            print(response, 55555555555555555555555555555555555555)
            if response.status_code != 200:
                return Response({'code': 400, 'msg': '无法获取 OSS 图片'}, status=400)

            img1_bytes = response.content  # OSS 图片字节数据
            img1_base64 = base64.b64encode(img1_bytes).decode("utf-8")

            # 调用人脸比对逻辑
            res = face.face_recognition(img1_base64, img2_base64)

            return Response({'code': 200, 'msg': res}, status=200)

        except Exception as e:
            return Response({'code': 500, 'msg': f'处理错误: {str(e)}'}, status=500)


class UserBrowserView(APIView):
    def get(self, request):
        user_id = request.query_params.get('user_id')
        if user_id:
            browserlist = UserBrowse.objects.filter(user_id=user_id).all()
            ids = [i.topid_id for i in browserlist]
            print(ids, 1111111111111111)
            ids = set(ids)
            print(ids, 222222222222222222)
            tops = Godds.objects.filter(topid__in=ids).all().order_by('-sale')[:15]
            goods = GoodsSerializer(tops, many=True)
            return Response({'code': 200, 'msg': 'ok', 'data': goods.data})
        else:
            goods = Godds.objects.all().order_by('-sale')
            datas = GoodsSerializer(goods, many=True)
            return Response({'code': 400, 'msg': 'error', 'data': datas.data})


class UserGoodsView(APIView):
    def get(self, request):
        userid = request.query_params.get('ussr_id')
        if userid:
            # 获取用户浏览记录
            goods = UserBrowse.objects.filter(user_id=userid).all()
            # 获取商品id列表
            ids = [i.goods_id for i in goods]

            print('2', ids)
            # 获取用户id列表
            userlist = UserBrowse.objects.filter(goods__in=ids).values('user_id')[:10]
            userid = [i['user_id'] for i in userlist if i['user_id'] != userid]
            other_goods = UserBrowse.objects.filter(user_id__in=userid).values('goods_id')
            print('3', other_goods)
            other_goods_id = [i['goods_id'] for i in other_goods]
            print('4', other_goods_id)
            diff = set(other_goods_id).difference(set(ids))
            print('5', diff)
            top_goods = Godds.objects.filter(id__in=diff).order_by('-sale')[:20]
            data = GoodsSerializer(top_goods, many=True)
            return Response({'code': 200, 'msg': 'ok', 'data': data.data})
        else:
            goods = Godds.objects.all()
            datas = GoodsSerializer(goods, many=True)
            return Response({'code': 400, 'msg': 'ok', 'data': datas.data})


# 高级写法
def get_csv(request):
    # 提取数据库中的商品id和用户id
    data = UserBrowse.objects.values('user_id', 'goods_id')

    # 指定文件夹路径
    doc_folder = os.path.join(os.getcwd(), 'doc')  # 当前项目路径下的 doc 文件夹
    os.makedirs(doc_folder, exist_ok=True)  # 如果文件夹不存在则创建

    # 指定文件路径
    file_path = os.path.join(doc_folder, 'goods_users.csv')

    # 写入 CSV 文件
    with open(file_path, mode='w', newline='', encoding='utf-8') as file:
        writer = csv.writer(file)
        # 写入表头
        writer.writerow(['user_id', 'goods_id'])
        # 写入表数据
        for row in data:
            writer.writerow([row['user_id'], row['goods_id']])

    # 返回文件存储成功的响应
    return JsonResponse({'message': 'CSV file saved successfully', 'file_path': file_path})


# 读取 CSV 文件并将其存储为 pandas.DataFrame。
# 创建用户和商品的唯一列表，同时创建用户和商品到其索引的映射。
# 创建一个零矩阵 data 用于存储用户 - 商品矩阵，将用户对商品的交互标记为 1（可根据实际情况修改交互的标记）。
# 遍历 DataFrame 的每一行，根据映射将用户和商品的交互标记添加到 data 矩阵中


from tools.services import RecommendationService


class RecommendView(APIView):
    """
    用户商品推荐视图 (基于类的视图)
    """

    # # 要求用户认证
    # permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        """
        处理 GET 请求，根据登录用户推荐商品并返回 JSON 响应。
        """
        # 获取当前登录用户的 ID
        user_id = request.GET.get('user_id')
        user_id = int(user_id)

        # 推荐服务实例（假设 CSV 文件路径为 'doc/goods_users.csv'）
        csv_path = 'doc/goods_users.csv'
        recommendation_service = RecommendationService(csv_path)

        # 加载数据
        recommendation_service.load_data()

        # 获取推荐商品列表
        recommended_goods = recommendation_service.recommend_items(user_id=user_id, top_n=20)

        # 返回推荐商品作为 JSON 响应
        return Response({
            "user_id": user_id,
            "recommended_goods": recommended_goods
        })

import random
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
class TestWebsocketEcharts(APIView):
    def get(self, request):
        list1 = {"datalist":['草药','鲜花','苹果'],"valuelist":[random.randint(10,80),random.randint(10,80),random.randint(10,80)]}

        channel_layer = get_channel_layer()

        async_to_sync(channel_layer.group_send)(
            'abc',#房间组名
            {
                'type':'send_to_chrome', #消费者中处理的函数
                'data':list1
            }
        )
        return JsonResponse({"code":200,"msg":"更新数据成功"})



from rest_framework.response import Response
from rest_framework.views import APIView
from tools.faissdb import myfaiss
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import CharacterTextSplitter
from langchain_community.llms import Tongyi

def generate_questions(movie_content):
    """使用通义大模型生成问题"""
    llm = Tongyi()

    # 创建提示模板
    template = """
       基于以下电影相关内容，生成50个可能的用户问题。问题要多样化，包括但不限于：
       - 询问特定电影的评分
       - 询问某个类型最受欢迎的电影
       - 询问演员相关的电影
       - 询问导演的作品
       - 询问电影推荐

       请确保问题的形式多样，既有简单的直接问题，也有复杂的分析性问题。
       每个问题单独一行，不要编号。

       内容：
       {content}
       """

    prompt = PromptTemplate(
        input_variables=["content"],
        template=template
    )

    # 生成问题
    questions = llm.invoke(prompt.format(content=movie_content))
    return questions.strip().split('\n')


class InitializeIndexes(APIView):
    """
      初始化向量数据库的索引
      """

    def post(self, request):
        try:
            # 1. 读取电影数据
            movie_file_path = "D:\\jiyun\\p5\\project\\login\\app\\data\\movie.txt"
            with open(movie_file_path, 'r', encoding='utf-8') as f:
                movie_content = f.read()

            # 2. 生成问题
            questions = generate_questions(movie_content)

            # 3. 将生成的问题保存到ask.txt
            ask_file_path = "D:\\jiyun\\p5\\project\\login\\app\\data\\ask.txt"
            with open(ask_file_path, 'w', encoding='utf-8') as f:
                f.write('\n'.join(questions))

            # 4. 初始化向量数据库
            # 处理电影数据
            doc = TextLoader(movie_file_path, encoding='utf-8').load()
            spliter = CharacterTextSplitter(chunk_size=20, chunk_overlap=5)
            chunks = spliter.split_documents(doc)
            myfaiss.add(chunks, "movies")

            # 处理问题数据
            ask_doc = TextLoader(ask_file_path, encoding='utf-8').load()
            ask_chunks = spliter.split_documents(ask_doc)
            myfaiss.add(ask_chunks, "ask")

            return Response({
                "code": 200,
                "message": "Questions generated and indexes initialized successfully.",
                "questions_count": len(questions)
            })

        except Exception as e:
            return Response({
                "code": 500,
                "message": f"Error occurred: {str(e)}"
            })

    def get(self, request):
        question = request.GET.get("ask", "")
        ask_results = myfaiss.search(question, "ask.txt", 3)
        print(ask_results)
        similar_questions = [res.page_content for res in ask_results]

        all_answers = []
        for sq in similar_questions:
            res = myfaiss.search(sq, "movies", 3)
            print(res)
            all_answers.extend([r.page_content for r in res])

        return Response({
            "code": 200,
            "similar_questions": similar_questions,
            "answers": all_answers
        })

